import re

from config import config
from huawei_api import HuaweiApi
from io import led
from log import Log
from net import NetworkStatus, Ap
from rtc import RTC_Helper
from uart import uart_2

log = Log(tag='Business')
DELIMITER = '\r\n'


class UART_Command:
    @staticmethod
    def send_command(cmd):
        if len(cmd) > 60:
            cmd = cmd[:60]
        cmd = '\r\n%s\r\n' % cmd
        uart_2.write(cmd)
        log.info('Write CMD [%s]' % cmd)

    @staticmethod
    def send_get_time_command():
        UART_Command.send_command('DATE\r\nTIME')

    @staticmethod
    def report_mac(mac):
        UART_Command.send_command('WMAC %s' % mac)

    @staticmethod
    def show_msg(msg):
        UART_Command.send_command('WRESP MSG %s' % msg)

    @staticmethod
    def show(msg):
        UART_Command.show_msg(msg)

    @staticmethod
    def error(msg):
        UART_Command.send_command('WRESP ERROR %s' % msg)

    @staticmethod
    def failure(msg):
        UART_Command.send_command('WRESP FAILURE %s' % msg)

    @staticmethod
    def sending():
        UART_Command.send_command('WRESP SENDING')

    @staticmethod
    def clean_screen():
        UART_Command.send_command('WRESP CLS')

    @staticmethod
    def ok():
        UART_Command.send_command('WRESP OK')


class CommandResolver:
    def __init__(self, handler):
        self.__handler = handler
        self.__buffer = ''

    def append_command(self, data):
        data = data.decode()
        for c in data:
            if c in DELIMITER:
                self.__on_new_line()
            else:
                self.__buffer += c

    def __on_new_line(self):
        line = self.__buffer.strip(' \r\n')
        if not line:
            return
        self.__buffer = ''
        match_res = re.match(r'^(\w+)\s?(\S*)\s?\S*$', line)
        if match_res:
            type = match_res.group(1)
            data = match_res.group(2)
            self.__handler.on_data(type, data)
            return
        match_res = re.match(r'(\w+)\sA\s(\d+)\s(\d+)\s(\d+)', line)
        if match_res:
            type = match_res.group(1)
            n1 = match_res.group(2)
            n2 = match_res.group(3)
            n3 = match_res.group(4)
            self.__resolve_datetime(type, n1, n2, n3)
            return
        log.warn('Invalidate command: [%s]' % line)

    def __resolve_datetime(self, type, n1, n2, n3):
        try:
            n1 = int(n1)
            n2 = int(n2)
            n3 = int(n3)
        except Exception as e:
            log.warn('Error on parse datetime string: %s' % e)
            return
        if type == 'DATE':
            self.__handler.on_date(n1, n2, n3)
        elif type == 'TIME':
            self.__handler.on_time(n1, n2, n3)
        else:
            log.warn('Invalidate datetime command :%s %s %s %s' % (type, n1, n2, n3))


AP_SSID_PREFIX = 'MIT-WIFI-'
AP_PASSWORD = 'monolithiot'


class CommandHandler:
    def __init__(self):
        self.__date = ()
        self.__time = ()
        self.__data = {}
        self.__api = HuaweiApi(config=config.api())
        self.__ap = Ap(ssid=CommandHandler.__get_ssid(), password=AP_PASSWORD)

    @staticmethod
    def __get_ssid():
        return AP_SSID_PREFIX + NetworkStatus.get_mac()[-4:]

    def on_date(self, year, month, day):
        self.__date = (year, month, day)
        if len(self.__time):
            self.__sync_datetime()

    def on_time(self, hour, minute, second):
        self.__time = (hour, minute, second)
        if len(self.__date):
            self.__sync_datetime()

    def __sync_datetime(self):
        RTC_Helper.set_time(self.__date[0], self.__date[1], self.__date[2], self.__time[0], self.__time[1],
                            self.__time[2])
        self.__date = ()
        self.__time = ()
        log.info('Set datetime [%s]' % RTC_Helper.current_time_as_string())

    def on_data(self, type, data):
        if type == 'END':
            self.__commit_data()
            return
        if type == 'MAC':
            self.__report_mac()
            return
        if type == 'STAT':
            self.__report_status()
            return
        if type == 'AP':
            self.__config_ap(data)
        self.__data[type] = data

    def __config_ap(self, op):
        if op == 'START':
            self.__ap.start()
        elif op == 'STOP':
            self.__ap.stop()
        else:
            log.warn('Invalidate AP OP [%s]' % op)

    def __commit_data(self):
        log.debug('Commit: %s' % self.__data)
        UART_Command.sending()
        try:
            led.on()
            res = self.__api.post_data(self.__data, NetworkStatus.get_mac())
        except Exception as e:
            log.error('Error on HttpReq', e)
            UART_Command.error('Network:%s' % repr(e))
            return
        finally:
            led.off()
        self.__data = {}
        status, result_str = self.__api.as_result_string(res)
        if status:
            UART_Command.ok()
        else:
            UART_Command.error(result_str)
            log.error('Error Response: [%s]' % result_str)

    def __report_mac(self):
        mac = NetworkStatus.get_mac()
        log.debug('Report Mac: %s' % mac)
        UART_Command.report_mac(mac)

    def __report_status(self):
        pass

